package net.flowas.genericcrud.audit.impl;

import static net.flowas.genericcrud.rest.CrudConstant.MODEL_TYPE;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import net.flowas.genericcrud.audit.ActionType;
import net.flowas.genericcrud.audit.AuditService;
import net.flowas.genericcrud.audit.model.AuditValue;
import net.flowas.genericcrud.audit.model.Comment;

public class AuditServiceImpl implements AuditService{
	private static final String AUDIT_FOR = "auditFor";
	private EntityManager em;
    
	public void setEm(EntityManager em) {
		this.em = em;
	}
	@Override
	public void mark(String modelType, ActionType action, Long id, Map<String,Object> data) {
		switch (action) {
		case COMMENT:			
			saveComment(modelType,id,data);
			break;
        case BROWSE:
        	changeAuditCount(modelType,id,"browseNum","+");
        	break;
        case LIKE:
        	changeAuditCount(modelType,id,"likeNum","+");
        	break;
        case FOLLOW:
        	changeAuditCount(modelType,id,"followNum","+");
        	break;
        case CANCEL_LIKE:
        	changeAuditCount(modelType,id,"likeNum","-");
        	break;
        case CANCEL_FOLLOW:
        	changeAuditCount(modelType,id,"followNum","-");
        	break;
        case BUY:
        case REMOVED:
		default:
			break;
		}
	}
	
	@Override
	public AuditValue get(String modelType, Long id) {
		String qlString = "select o from AuditValue o where o.modelType = :modelType and o.auditFor = :auditFor";
		Query query = em.createQuery(qlString);
		query.setParameter(MODEL_TYPE, modelType);
		query.setParameter(AUDIT_FOR, id);
		if(query.getResultList().isEmpty() ){
           return null;
        } else{
		   return (AuditValue) query.getSingleResult();
        }
	}
	@Override
	public List<Comment> findConments(String modelType, Long id) {
		String qlString = "select o from Comment o where o.modelType = :modelType and o.auditFor = :auditFor";
		Query query = em.createQuery(qlString);
		query.setParameter(MODEL_TYPE, modelType);
		query.setParameter(AUDIT_FOR, id);
		return  query.getResultList();
	}	
	private void changeAuditCount(String modelType, Long id, String colunmName,String operator) {
		String qlString="update AuditValue a set a.@colunmName@= a.@colunmName@ @operator@ 1 where a.modelType = :modelType and a.auditFor = :auditFor";
		qlString=qlString.replaceAll("@colunmName@", colunmName);
		qlString=qlString.replaceAll("@operator@", operator);
		Query query = em.createQuery(qlString);
		query.setParameter(MODEL_TYPE, modelType);
		query.setParameter(AUDIT_FOR, id);
		int result = query.executeUpdate();
		if(result==0) {
			AuditValue audit=new AuditValue();
			audit.setAuditFor(id);
			audit.setModelType(modelType);
			em.persist(audit);	
			query.executeUpdate();
		}			
	}	
	private void saveComment(String modelType, Long id, Map<String,Object> data) {
		Comment comment =new Comment();
		if(data.containsKey("userId")) {
			comment.setUserId((String) data.get("userId"));
		}else{
			throw new IllegalArgumentException("userId is missing!");
		}
		if(data.containsKey("content")) {
			comment.setContent((String) data.get("content"));
		}else{
			throw new IllegalArgumentException("content is missing!");
		}
		comment.setAuditFor(id);
		comment.setModelType(modelType);
		em.persist(comment);
	}
}
